package com.bschlearn.group.interceptor;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.bschlearn.group.common.util.JwtUtil;
import com.bschlearn.group.message.BaseRsp;
import com.bschlearn.group.model.User;

import io.jsonwebtoken.Claims;

public class AllRequestInterceptor implements HandlerInterceptor{

	// 实例化log
	private final static Logger log = LoggerFactory.getLogger(AllRequestInterceptor.class);
	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		log.info(request.getRequestURL()+"--"+request.getMethod()+"---被拦截！");
		
		HttpSession session = request.getSession();
		
		User user = (User)session.getAttribute("user");
		if(null == user) {

			// 获取token
			String token = request.getParameter("token");
			if(null == token) {
				returnJson(response,BaseRsp.errorMsg("登陆已过期，请重新登陆!").toJSON());
				return false;
			}
			
			try {
				
				Claims jwt = JwtUtil.inst().parseJWT(token);
				
				@SuppressWarnings("unchecked")
				Map<String,Object> map = (Map<String,Object>) jwt.get("user");
				
				// 获取用户信息
				user = mapToEntity(map,User.class);
				
				// 获取登陆时间
				long loginTime = (long) jwt.get("loginTime");
				
				// 获取过期时间
				int expireTime = (int)jwt.get("expireTime");
				
				// 获取当前时间
				long nowMillis = System.currentTimeMillis();
				
				if(loginTime+expireTime < nowMillis) {
					returnJson(response,BaseRsp.errorMsg("session 过期!").toJSON());
					return false;
				}
				
				// 设置session
				session.setAttribute("user", user);
				
				// 设置session过期时间
				int sessionExpireTime = Integer.valueOf((expireTime+loginTime-nowMillis)/1000+"");
				
				session.setMaxInactiveInterval(sessionExpireTime);
				
				return true;
				
			}catch (Exception e) {
				log.error("token 异常",e);
				returnJson(response,BaseRsp.errorMsg("token 过期或有异常!").toJSON());
				return false;
			}
		}else {
			return true;
		}
	}
	
	 private void returnJson(HttpServletResponse response, String json) throws Exception{
	        PrintWriter writer = null;
	        response.setCharacterEncoding("UTF-8");
	        response.setContentType("text/html; charset=utf-8");
	        try {
	            writer = response.getWriter();
	            writer.print(json);
	 
	        } catch (IOException e) {
	            log.error("response error",e);
	        } finally {
	            if (writer != null)
	                writer.close();
	        }
	 }
	 
	 /**
	 * Map转实体类
	 * @param map 需要初始化的数据，key字段必须与实体类的成员名字一样，否则赋值为空
	 * @param entity  需要转化成的实体类
	 * @return
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 */
	public static <T> T mapToEntity(Map<String, Object> map, Class<T> entity) throws InstantiationException, IllegalAccessException {
		T t = null;
			t = entity.newInstance();
			for(Field field : entity.getDeclaredFields()) {
				if (map.containsKey(field.getName())) {
					boolean flag = field.isAccessible();
		            field.setAccessible(true);
		            Object object = map.get(field.getName());
		            if (object!= null && field.getType().isAssignableFrom(object.getClass())) {
		            	 field.set(t, object);
					}
		            field.setAccessible(flag);
				}
			}
			return t;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
		
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
	}
	
	

}
